package looting;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Container class for a LootTable. The LootItems in this class must be added in
 * the order that they stack in-game to get the most natural pickup behavior.
 * The items are hashed 2 different ways for fast lookups.
 */
public class LootTable implements Iterable<LootItem> {
	private Map<String, LootItem> lootByName = new HashMap<String, LootItem>();
	private LinkedHashMap<Integer, LootItem> lootByID = new LinkedHashMap<Integer, LootItem>();

	public LootTable(LootItem... items) {
		for (LootItem i : items) {
			lootByName.put(i.getName().toLowerCase(), i);
			lootByID.put(i.getId(), i);
		}
	}

	public int getSize() {
		return lootByName.size();
	}

	public int[] getIDs() {
		Integer[] ids = lootByID.keySet().toArray(new Integer[lootByID.keySet().size()]);
		int[] ids2 = new int[ids.length];

		for (int i = 0; i < ids.length; i++) {
			ids2[i] = ids[1];
		}

		return ids2;
	}

	public void add(LootItem... items) {
		if (items == null) {
			return;
		}

		for (LootItem i : items) {
			if (i == null) {
				continue;
			}

			lootByName.put(i.getName().toLowerCase(), i);
			lootByID.put(i.getId(), i);
		}
	}

	/** add the item using a different id (way to index by noted id) */
	public void add(int id, LootItem item) {
		lootByName.put(item.getName().toLowerCase(), item);
		lootByID.put(id, item);

	}

	public LootItem[] getItems(String name) {
		if (name == null) {
			return new LootItem[] {};
		}

		ArrayList<LootItem> items = new ArrayList<LootItem>();
		for (LootItem li : this) {
			if (li.getName().equalsIgnoreCase(name)) {
				items.add(li);
			}
		}

		return items.toArray(new LootItem[items.size()]);
	}

	public LootItem[] getCloseMatches(String name) {
		if (name == null) {
			return new LootItem[] {};
		}

		ArrayList<LootItem> items = new ArrayList<LootItem>();
		for (LootItem li : this) {
			if (li.getName().toLowerCase().contains(name.toLowerCase())) {
				items.add(li);
			}
		}

		return items.toArray(new LootItem[items.size()]);
	}

	public LootItem get(int id) {
		for (LootItem li : this) {
			if (li.idMatches(id)) {
				return li;
			}
		}
		return null;
	}

	public LootItem get(String name) {
		for (LootItem li : this) {
			if (li.nameMatches(name)) {
				return li;
			}
		}
		return null;
	}

	public void clear() {
		lootByName.clear();
		lootByID.clear();
	}

	@Override
	public Iterator<LootItem> iterator() {
		return lootByID.values().iterator();
	}

	public void addToTop(LootItem... items) {
		LinkedHashMap<Integer, LootItem> newByID = new LinkedHashMap<Integer, LootItem>();

		for (LootItem i : items) {
			lootByName.put(i.getName().toLowerCase(), i);
			newByID.put(i.getId(), i);
		}

		for (LootItem i : this) {
			newByID.put(i.getId(), i);
		}

		lootByID = newByID;
	}

	// this needs to be added to LootTable
	public void removeLoot(LootItem item) {
		lootByName.remove(item.getName().toLowerCase());
		lootByID.remove(item.getId());
	}

	public void removeLoot(String itemName) {
		LootItem item = get(itemName);
		if (item != null) {
			lootByName.remove(item.getName().toLowerCase());
			lootByID.remove(item.getId());
		}
	}

	public void loadMasterTable(String location) {
		try {
			InputStream stream = new FileInputStream(location);
			add(LootItemLoader.getLootItemsFromStream(stream));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public String toString() {
		return Arrays.toString(lootByName.values().toArray());
	}
}